<?php

namespace App\Service\Fee\FeishuApply;

use App\Enums\BaseErrorCode;
use App\Enums\Check\CheckEnum;
use App\Enums\Fee\FeeEnum;
use App\Enums\OpenShop\InvestmentPromotion\MainProcessEnum;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderEnum;
use App\Enums\OpenShop\InvestmentPromotion\SiteLocationEnum;
use App\Enums\OpenShop\InvestmentPromotion\UserIdentityCardEnum;
use App\Enums\OpenShop\MissionTemplateEnum;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\Rms\RmsShopApi;
use App\Models\Cruise\CruiseCheckAgainstModel;
use App\Models\Fee\FeeAnnualChangesModel;
use App\Models\Fee\FeeAnnualOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopAddressModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopOrganizationManageUserModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderPayHistoryModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserIdentityCardModel;
use App\Models\OpenShop\ShopCheckAccept\OpenShopCheckAcceptModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use App\Remote\Rms\RmsShopRemote;
use App\Remote\Rms\RmsUserRemote;
use App\Service\OpenShop\Feishu\OrganizationManageService;
use App\Service\OpenShop\Feishu\PermissionService;
use App\Service\OpenShop\Wap\SignOrderService;
use App\Service\Rms\ShopService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class FeeAnnualOrderService
{
    /**
     * 年费列表
     * @param $userInfo
     * @param $scope
     * @param $payStatus
     * @param $status
     * @param $param
     * @param $pageSize
     * @param $pageNum
     * @param int $export 是否导出
     * @return array
     */
    public static function getList($userInfo, $scope, $payStatus, $status, $param, $pageSize, $pageNum, int $export = 0): array
    {
        $shopIdsPower   = [];
        $managerId      = 0;
        $managerShopIds = [];
        if ($scope != PermissionService::PERMISSION_ALL) {
            if ($scope == PermissionService::PERMISSION_DENY) {
                return [
                    'list'     => [],
                    'count'    => 0,
                    'pageNum'  => $pageNum,
                    'pageSize' => $pageSize,
                ];
            }
            if (isset($userInfo->position) && ($userInfo->position == SiteLocationEnum::POSITION_PROVINCE_CHIEF || $scope == PermissionService::PERMISSION_PROVINCE)) {
                $provinceRes  = true;
                $shopIdsPower = self::getShopIdsByProvinceUserId($userInfo->userId);
            } elseif ($scope == PermissionService::PERMISSION_CITY) {
                $provinceRes  = true;
                $shopIdsPower = self::getShopIdsByCityUserId($userInfo->userId);
            } else {
                $managerId = $userInfo->userId;
            }
        }

        if ($managerId) {
            //获取运营督导下的所有的门店ID
            $managerRes     = true;
            $managerShopIds = OpenShopCheckAcceptModel::query()
                                                      ->where('managerId', $managerId)
                                                      ->with(['mainProcessRel'])
                                                      ->get()
                                                      ->map(function ($item) {
                                                          if ($item->mainProcessRel != null) {
                                                              return $item->mainProcessRel->shopId;
                                                          }
                                                      })->toArray();
        }

        $search   = false;
        $userName = '';
        $shopIds  = [];
        if (is_numeric($param)) {
            $shopCode = $param;
        } else {
            $userName = $param;
        }

        //通过shopCode获得门店ID
        if (isset($shopCode)) {
            $search    = true;
            $signOrder = OpenShopSignOrderModel::query()
                                               ->with(['mainProcessRel'])
                                               ->where('shopCode', $shopCode)
                                               ->first();
            if ($signOrder !== null) {
                $shopIds[] = optional($signOrder->mainProcessRel)->shopId;
            }
        }
        //根据姓名模糊shopId
        if (mb_strlen($userName)) {
            $search = true;
            OpenShopUserIdentityCardModel::query()
                                         ->with(['mainProcessRel'])
                                         ->where('name', 'like', "%$userName%")
                                         ->get()
                                         ->each(function ($item) use (&$shopIds) {
                                             if ($item->mainProcessRel != null) {
                                                 foreach ($item->mainProcessRel as $value) {
                                                     $shopIds[] = $value->shopId;
                                                 }
                                             }
                                         });
        }

        //今天的开始时间
        $startToday = strtotime(date('Y-m-d') . ' 00:00:00');
        $paginator  = FeeAnnualOrderModel::query()
                                         ->when(isset($provinceRes), function ($query) use ($shopIdsPower) {
                                             $query->whereIn('shopId', $shopIdsPower);
                                         })
                                         ->when(isset($managerRes), function ($query) use ($managerShopIds) {
                                             $query->whereIn('shopId', $managerShopIds);
                                         })
                                         ->when($search, function ($query) use ($shopIds) {
                                             $query->whereIn('shopId', $shopIds);
                                         })
                                         ->when($payStatus == FeeAnnualOrderModel::PAY_STATUS_OK, function ($query) {
                                             $query->where('payStatus', FeeAnnualOrderModel::PAY_STATUS_OK);
                                         })
                                         ->when($payStatus == FeeAnnualOrderModel::PAY_STATUS_WAIT, function ($query) {
                                             $query->whereIn('payStatus', [
                                                 FeeAnnualOrderModel::PAY_STATUS_WAIT,
                                                 FeeAnnualOrderModel::PAY_STATUS_PART
                                             ]);
                                         })
                                         ->when(mb_strlen($status), function ($query) use ($status, $startToday) {
                                             switch ($status) {
                                                 case FeeEnum::SCREEN_STATUS_NINETY:
                                                     //获得近90天的
                                                     $ninetyTime = strtotime(date('Y-m-d',
                                                             strtotime('+90day')) . ' 23:59:59');
                                                     $query->where('endTime', '>', $startToday)
                                                           ->where('endTime', '<=', $ninetyTime);
                                                     break;
                                                 case FeeEnum::SCREEN_STATUS_SIXTY:
                                                     //获得近60天的
                                                     $sixtyTime = strtotime(date('Y-m-d',
                                                             strtotime('+60day')) . ' 23:59:59');
                                                     $query->where('endTime', '>', $startToday)
                                                           ->where('endTime', '<=', $sixtyTime);
                                                     break;
                                                 case FeeEnum::SCREEN_STATUS_THIRTY:
                                                     //获得近30天的
                                                     $thirtyTime = strtotime(date('Y-m-d',
                                                             strtotime('+30day')) . ' 23:59:59');
                                                     $query->where('endTime', '>', $startToday)
                                                           ->where('endTime', '<=', $thirtyTime);
                                                     break;
                                                 case FeeEnum::SCREEN_STATUS_OVERDUE:
                                                     //过期的
                                                     $query->where('endTime', '<', time());
                                                     break;
                                                 case FeeEnum::SCREEN_STATUS_TODAY:
                                                     //获得当天的
                                                     $endToday = strtotime(date('Y-m-d') . ' 23:59:59');
                                                     $query->where('endTime', '>', $startToday)
                                                           ->where('endTime', '<=', $endToday);
                                                     break;
                                                 default:
                                                     break;
                                             }
                                         })
                                         ->with(['signOrderRel', 'siteLocationRel', 'identityCardRel'])
                                         ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        $shopCodes = collect($paginator->pluck('signOrderRel')->toArray())->pluck('shopCode')->toArray();

        $shopInfo   = RmsShopRemote::getShopFieldsByCodes($shopCodes, ['shopCode', 'name'])['shopList'] ?? [];
        $shopFormat = array_column($shopInfo, 'name', 'shopCode');

        $list = $paginator->map(function ($item) use ($shopFormat) {
            $expiresTime = self::expiresTime($item->endTime);
            $shopCode    = optional($item->signOrderRel)->shopCode;
            return [
                'id'          => $item->id,
                'shopCode'    => $shopCode,
                'userName'    => optional($item->identityCardRel)->name,
                'shopName'    => $shopFormat[$shopCode] ?? '',  // 门店名称,
                'payStatus'   => $item->payStatusText,
                'status'      => $item->statusText,
                'feeOrderNo'  => $item->feeOrderNo,
                'price'       => $item->shouldPayPrice,
                'shopAddress' => optional($item->siteLocationRel)->cityArea ?: '-',
                'endTime'     => formatDateYmd($item->endTime),
                'endTimeText' => $expiresTime['long'] ?? '待完成',
                'isShow'      => FeeEnum::IS_SHOW_OFF
            ];
        });

        return [
            'list'     => $list,
            'count'    => $paginator->total(),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize,
        ];

    }

    public static function detail(int $id)
    {
        $feeModel = FeeAnnualOrderModel::query()
                                       ->with([
                                           'signOrderRel',
                                           'siteLocationRel',
                                           'userBaseInfoRel',
                                           'identityCardRel',
                                           'startBusinessRel',
                                           'mainProcessRel'
                                       ])
                                       ->where('id', $id)
                                       ->first();

        $expiresTime = self::expiresTime($feeModel->endTime);
        $feeInfo     = [];
        if ($feeModel->manageFee) {
            $feeInfo[] = [
                'text'  => FeeEnum::FEE_PRICE_TYPE[FeeEnum::FEE_MANAGE] ?? '费用价格' . ':',
                'value' => $feeModel->manageFee
            ];
        }
        if ($feeModel->systemFee) {
            $feeInfo[] = [
                'text'  => FeeEnum::FEE_PRICE_TYPE[FeeEnum::FEE_SYSTEM] ?? '费用价格' . ':',
                'value' => $feeModel->systemFee
            ];
        }
        $shopCode = optional($feeModel->signOrderRel)->shopCode;

        $startFeeTime   = $feeModel->mainProcessRel->startFeeTime;
        $startFeeTimeMD = date('md', strtotime($startFeeTime));

        $year = $feeModel->startYear;
        if (!$year) {

            // 兼容一下
            $year = date('Y', $feeModel->endTime);
        }

        return [
            'baseInfo' => [
                'id'          => $feeModel->id,
                'feeOrderNo'  => $feeModel->feeOrderNo,
                'signOrderNo' => optional($feeModel->siteLocationRel)->orderNo,
                'price'       => $feeModel->shouldPayPrice,
                'info'        => optional($feeModel->identityCardRel)->name . ' | ' . (UserIdentityCardEnum::GENDER[optional($feeModel->identityCardRel)->gender] ?: UserIdentityCardEnum::GENDER_1) . ' | ' . ((int)((date('Y') - date('Y',
                            strtotime(optional($feeModel->identityCardRel)->birthday) ?: time())))) . '岁',
                'mobile'      => optional($feeModel->userBaseInfoRel)->mobile ?: '-',
                'areaPrefix'  => optional($feeModel->siteLocationRel)->cityArea ?: '-',
                'address'     => optional($feeModel->siteLocationRel)->address ?: '-',
                'startTime'   => formatDate(optional($feeModel->startBusinessRel)->startBusinessTime ?: 0),
                'createdTime' => $feeModel->createdAt->toDateString(),
                'endTimeText' => $expiresTime['long'] ?? '待完成',
                'isShow'      => $expiresTime['isShow'] ?? FeeEnum::IS_SHOW_OFF,
                'status'      => $feeModel->statusText,
                'shopName'    => $shopCode ? ShopService::getShopNameByCode($shopCode) : '-',  // 门店名称,
                'shopCode'    => $shopCode,
                'expireTime'  => date('Y-m-d H:i:s', $feeModel->endTime),
                'indateStart' => date('Y.m.d', strtotime($year . $startFeeTimeMD) + 86400),
                'indateEnd'   => date('Y.m.d', strtotime(($year + 1) . $startFeeTimeMD))
            ],
            'feeInfo'  => $feeInfo
        ];
    }

    /**
     * 时间比较
     *
     * @param int $time
     * @return array
     */
    public static function expiresTime(int $time): array
    {
        $endTime = strtotime(date('Y-m-d') . ' 23:59:59');
        if ($time < $endTime) {
            return [
                'long'   => '已过期',
                'isShow' => FeeEnum::IS_SHOW_OFF,
            ];
        }
        $middle = (int)(($time - $endTime) / 86400);
        //仅有一天的时候特殊处理
        if ($middle == 1) {
            return [
                'long'   => '1天到期',
                'isShow' => FeeEnum::IS_SHOW_ON
            ];
        } else {
            return [
                'long'   => $middle . '天到期',
                'isShow' => FeeEnum::IS_SHOW_OFF
            ];
        }
    }


    public static function headTitle(object $userInfo, $scope)
    {
        $shopIdsPower   = [];
        $managerId      = 0;
        $managerShopIds = [];
        if ($scope != PermissionService::PERMISSION_ALL) {
            if ($scope == PermissionService::PERMISSION_DENY) {
                return '';
            }
            if (isset($userInfo->position) && ($userInfo->position == SiteLocationEnum::POSITION_PROVINCE_CHIEF || $scope == PermissionService::PERMISSION_PROVINCE)) {
                $provinceRes  = true;
                $shopIdsPower = self::getShopIdsByProvinceUserId($userInfo->userId);
            } elseif ($scope == PermissionService::PERMISSION_CITY) {
                $provinceRes  = true;
                $shopIdsPower = self::getShopIdsByCityUserId($userInfo->userId);
            } else {
                $managerId = $userInfo->userId;
            }
        }

        if ($managerId) {
            //获取运营督导下的所有的门店ID
            $managerRes     = true;
            $managerShopIds = OpenShopCheckAcceptModel::query()
                                                      ->where('managerId', $managerId)
                                                      ->with(['mainProcessRel'])
                                                      ->get()
                                                      ->map(function ($item) {
                                                          if ($item->mainProcessRel != null) {
                                                              return $item->mainProcessRel->shopId;
                                                          }
                                                      })->toArray();
        }

        //近30天的年费订单
        $count = FeeAnnualOrderModel::query()
                                    ->where('endTime', '<=',
                                        strtotime(date('Y-m-d', strtotime('+30day')) . ' 23:59:59'))
                                    ->where('endTime', '>', strtotime(date('Y-m-d') . ' 00:00:00'))
                                    ->whereIn('payStatus',
                                        [FeeAnnualOrderModel::PAY_STATUS_WAIT, FeeAnnualOrderModel::PAY_STATUS_PART])
                                    ->when(isset($provinceRes), function ($query) use ($shopIdsPower) {
                                        $query->whereIn('shopId', $shopIdsPower);
                                    })
                                    ->when(isset($managerRes), function ($query) use ($managerShopIds) {
                                        $query->whereIn('shopId', $managerShopIds);
                                    })
                                    ->count();

        if ($count) {
            return '目前有' . $count . '笔年费订单即将过期（近30天），请重点关注！';
        } else {
            return '';
        }
    }

    public static function countStatusNumber($userInfo, $scope)
    {
        $shopIdsPower   = [];
        $managerId      = 0;
        $managerShopIds = [];
        if ($scope != PermissionService::PERMISSION_ALL) {
            if ($scope == PermissionService::PERMISSION_DENY) {
                return [
                    'total'   => 0,
                    'ninety'  => 0,
                    'sixty'   => 0,
                    'thirty'  => 0,
                    'today'   => 0,
                    'overdue' => 0
                ];
            }
            if (isset($userInfo->position) && ($userInfo->position == SiteLocationEnum::POSITION_PROVINCE_CHIEF || $scope == PermissionService::PERMISSION_PROVINCE)) {
                $provinceRes  = true;
                $shopIdsPower = self::getShopIdsByProvinceUserId($userInfo->userId);
            } elseif ($scope == PermissionService::PERMISSION_CITY) {
                $provinceRes  = true;
                $shopIdsPower = self::getShopIdsByCityUserId($userInfo->userId);
            } else {
                $managerId = $userInfo->userId;
            }
        }
        if ($managerId) {
            //获取运营督导下的所有的门店ID
            $managerRes     = true;
            $managerShopIds = OpenShopCheckAcceptModel::query()
                                                      ->where('managerId', $managerId)
                                                      ->with(['mainProcessRel'])
                                                      ->get()
                                                      ->map(function ($item) {
                                                          if ($item->mainProcessRel != null) {
                                                              return $item->mainProcessRel->shopId;
                                                          }
                                                      })->toArray();
        }
        $total   = 0;
        $ninety  = 0;
        $sixty   = 0;
        $thirty  = 0;
        $today   = 0;
        $overdue = 0;

        FeeAnnualOrderModel::query()
                           ->whereIn('payStatus',
                               [FeeAnnualOrderModel::PAY_STATUS_WAIT, FeeAnnualOrderModel::PAY_STATUS_PART])
                           ->when(isset($provinceRes), function ($query) use ($shopIdsPower) {
                               $query->whereIn('shopId', $shopIdsPower);
                           })
                           ->when(isset($managerRes), function ($query) use ($managerShopIds) {
                               $query->whereIn('shopId', $managerShopIds);
                           })
                           ->get()
                           ->each(function ($item) use (&$total, &$ninety, &$sixty, &$thirty, &$today, &$overdue) {
                               ++$total;
                               $ninetyTime = strtotime(date('Y-m-d', strtotime('+90day')) . ' 23:59:59');
                               if ($item->endTime > time() && $item->endTime <= $ninetyTime) {
                                   ++$ninety;
                               }
                               $sixtyTime = strtotime(date('Y-m-d', strtotime('+60day')) . ' 23:59:59');
                               if ($item->endTime > time() && $item->endTime <= $sixtyTime) {
                                   ++$sixty;
                               }
                               $thirtyTime = strtotime(date('Y-m-d', strtotime('+30day')) . ' 23:59:59');
                               if ($item->endTime > time() && $item->endTime <= $thirtyTime) {
                                   ++$thirty;
                               }
                               $endToday = strtotime(date('Y-m-d') . ' 23:59:59');
                               if ($item->endTime > time() && $item->endTime <= $endToday) {
                                   ++$today;
                               }
                               if ($item->endTime < time()) {
                                   ++$overdue;
                               }
                           });
        return [
            'total'   => $total,
            'ninety'  => $ninety,
            'sixty'   => $sixty,
            'thirty'  => $thirty,
            'today'   => $today,
            'overdue' => $overdue
        ];
    }

    /**
     * 查询是否支付完，截止到今天的年管理费
     * @param int $shopId
     * @return int
     */
    public static function feePayStatus(array $shopIds): array
    {
        $expiredShopIds = FeeAnnualOrderModel::query()
                                             ->whereIn('shopId', $shopIds)
                                             ->where('payStatus', '!=', FeeAnnualOrderModel::PAY_STATUS_OK)
                                             ->where('endTime', '<', time())
                                             ->pluck('shopId')
                                             ->toArray();

        $res = [];
        foreach ($shopIds as $shopId) {
            if (in_array($shopId, $expiredShopIds)) {
                $res[$shopId] = 0;
            } else {
                $res[$shopId] = 1;
            }
        }

        return $res;
    }

    /**
     * 获取过期时间，是否弹窗
     * @param int $shopId
     * @return array
     */
    public static function getExpired(int $shopId): array
    {
        //判断稽核是否触发违约支付
        $cruiseCheckAgainstModel = CruiseCheckAgainstModel::query()
                                                          ->where('shopId', $shopId)
                                                          ->where('status', CruiseCheckAgainstModel::STATUS_WAIT)
                                                          ->where('level', CruiseCheckAgainstModel::LEVEL_PUNISH)
                                                          ->where('endTime', '<=', time());
        if ($cruiseCheckAgainstModel->count()) {
            //根据shopId获得shopCode
            $shopCode = (new RmsShopApi())->getShopByIds([$shopId],
                    ['shopCode'])['data']['shopList'][0]['shopCode'] ?? 0;
            return [
                'showWindow'    => 1,
                'todayRepeated' => 0,
                'expiredDay'    => 0,
                'shopCode'      => $shopCode,
                'days'          => ceil((($cruiseCheckAgainstModel->value('endTime') + 8 * 86400) - time()) / 86400),
                'count'         => $cruiseCheckAgainstModel->count(),
                'businessIds'   => $cruiseCheckAgainstModel->pluck('id')->toArray(),
                'type'          => 'against', // 弹窗类型  fee 年费     against  稽核违约
            ];
        }


        $order = FeeAnnualOrderModel::query()
                                    ->where('shopId', $shopId)
                                    ->where('payStatus', '!=', FeeAnnualOrderModel::PAY_STATUS_OK)
                                    ->orderBy('endTime')
                                    ->first();

        if (!$order) {
            return [
                'showWindow'    => 0,     // 是否展示弹窗 0否 1是
                'todayRepeated' => 0,     // 今日是否重复弹窗 0否 1是
                'expiredDay'    => 0,     // 过期天数
                'days'          => 0,
                'shopCode'      => 0,
                'count'         => 0,
                'businessIds'   => [],
                'type'          => 'fee', // 弹窗类型  fee 年费     against  稽核违约
            ];
        }

        $expiredDay = (int)floor(($order->endTime - time()) / 86400);

        if ($expiredDay >= 30) {
            $todayRepeated = 0;
        } elseif ($expiredDay < 30 && $expiredDay > 0) {
            $todayRepeated = 1;
        } elseif ($expiredDay == 0) {
            $todayRepeated = 0;
        } else {
            $todayRepeated = 1;
        }

        return [
            'showWindow'    => $expiredDay < 30 ? 1 : 0,
            'todayRepeated' => $todayRepeated,
            'days'          => 0,
            'count'         => 0,
            'shopCode'      => 0,
            'expiredDay'    => $expiredDay,
            'businessIds'   => [],
            'type'          => 'fee',
        ];
    }


    public static function getShopIdsByProvinceUserId($userId)
    {
        $areaArr = OrganizationManageService::getProvinceList($userId);

        //桥梁
        $orderNos = OpenShopAddressModel::query()->whereIn('provinceCode', $areaArr)->pluck('orderNo');

        //获取门店ID
        return OpenShopMainProcessModel::query()
                                       ->whereIn('orderNo', $orderNos)
                                       ->pluck('shopId')
                                       ->toArray();
    }

    public static function getShopIdsByCityUserId(int $userId)
    {
        $cityCodes = [];
        OpenShopOrganizationManageUserModel::query()
            ->where('userId', $userId)
            ->where('type', OpenShopOrganizationManageUserModel::TYPE_CITY_MANAGER)
            ->get()
            ->map(function (OpenShopOrganizationManageUserModel $openShopOrganizationManageUserModel) use (&$cityCodes) {
                $cityCodes = array_merge($cityCodes, array_column($openShopOrganizationManageUserModel->addressCodesArr, 'cityCode'));
            });

        //桥梁
        $orderNos = OpenShopAddressModel::query()->whereIn('cityCode', $cityCodes)->pluck('orderNo');

        //获取门店ID
        return OpenShopMainProcessModel::query()
                                       ->whereIn('orderNo', $orderNos)
                                       ->pluck('shopId')
                                       ->toArray();
    }

    public static function webLists(
        string $feeOrderNo,
        array $shopIds,
        int $startTime,
        int $endTime,
        array $payStatus,
        int $pageNum,
        int $pageSize,
        int $export = 0
    ): array {
        @ini_set('memory_limit', '512M');
        $paginator = FeeAnnualOrderModel::query()
                                        ->with(['changesLogRel', 'mainProcessesRel'])
                                        ->when($feeOrderNo, function ($query) use ($feeOrderNo) {
                                            $query->where('feeOrderNo', $feeOrderNo);
                                        })
                                        ->when($shopIds, function ($query) use ($shopIds) {
                                            $query->whereIn('shopId', $shopIds);
                                        })
                                        ->when($startTime || $endTime, function ($query) use ($startTime, $endTime) {
                                            $query->whereBetween('endTime', [$startTime, $endTime]);
                                        })
                                        ->when($payStatus, function ($query) use ($payStatus) {
                                            $query->whereIn('payStatus', $payStatus);
                                        })
                                        ->orderBy('endTime')
                                        ->when(
                                            $export,
                                            function ($query) {
                                                return $query->get();
                                            },
                                            function ($query) use ($pageNum, $pageSize) {
                                                return $query->paginate($pageSize, ['*'], 'pageNum', $pageNum);
                                            }
                                        );

        if ($export == 0 && !$paginator->count()) {
            return [
                'list'     => [],
                'count'    => $paginator->total(),
                'pageNum'  => $pageNum,
                'pageSize' => $pageSize,
            ];
        }

        if ($export) {
            $dbShopIds = $paginator->pluck('shopId')->toArray();
        } else {
            $dbShopIds = collect($paginator->items())->pluck('shopId')->toArray();
        }
        $shopInfos = collect((new RmsShopApi())
                ->getShopByIds($dbShopIds, ['id', 'shopCode', 'name'], true)['data']['shopList'] ?? [])
            ->keyBy('id');

        $list = $paginator->map(function ($item) use ($shopInfos) {

            $showReduce = $showDelay = 1;

            // 已支付 - 隐藏延期/减免按钮
            if ($item->payStatus == FeeAnnualOrderModel::PAY_STATUS_OK) {
                $showReduce = 0;
                $showDelay  = 0;
            }

            // 年费开始计算日期
            $calculateTime = '-';
            foreach ($item->mainProcessesRel as $mainProcessRel) {
                if ($mainProcessRel->childLocationOrder == MainProcessEnum::CHILD_ORDER_0) {
                    $calculateTime = $mainProcessRel->startFeeTime;
                }
            }

            return [
                'feeOrderNo'     => $item->feeOrderNo,
                'shopCode'       => $shopInfos[$item->shopId]['shopCode'] ?? '',
                'shopName'       => $shopInfos[$item->shopId]['name'] ?? '',
                'shouldPayPrice' => $item->shouldPayPrice,
                'goodsDetail'    => [
                    '年管理费：' . ($item->manageFee / 100) . '元',
                    '数字化系统年服务费：' . ($item->systemFee / 100) . '元',
                ],
                'payPrice'       => $item->payPrice,
                'endTime'        => date('Y-m-d H:i:s', $item->endTime),
                'payStatus'      => $item->payStatus,
                'payStatusText'  => FeeAnnualOrderModel::STATUS_MAP[$item->payStatus] ?? '',
                'showDelay'      => $showDelay,
                'showReduce'     => $showReduce,
                'calculateTime'  => $calculateTime,
                'operateLog'     => $item->changesLogRel->map(function ($log) {
                    return [
                        'id'        => $log->id,
                        'createdAt' => date('Y-m-d H:i:s', $log->createdAt),
                        'userName'  => $log->createdByName,
                        'content'   => $log->content,
                        'remark'    => $log->remark,
                        'image'     => $log->image
                    ];
                })->sortByDesc("id")->values(),
            ];
        });

        // 导出
        if ($export) {
            self::exportFeeOrders($list);
        }

        return [
            'list'     => $list,
            'count'    => $paginator->total(),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize,
        ];
    }

    private static function checkFeeOrder(string $feeOrderNo)
    {
        $model = FeeAnnualOrderModel::query()->where('feeOrderNo', $feeOrderNo)->first();
        if (!$model) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "找不到的年费订单");
        }

        if ($model->payStatus == FeeAnnualOrderModel::PAY_STATUS_OK) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "已支付订单无法操作");
        }

        return $model;
    }

    /**
     * 延期
     * @param string $feeOrderNo
     * @param int $day
     * @param string $date
     * @param int $userId
     * @param string $userName
     * @param string $remark
     * @param string $image
     * @return array
     */
    public static function delay(
        string $feeOrderNo,
        int $day,
        string $date,
        int $userId,
        string $userName,
        string $remark,
        string $image = ""
    ): array {
        $feeOrderModel = self::checkFeeOrder($feeOrderNo);
        $beforeEndTime = $feeOrderModel->endTime;

        DB::beginTransaction();

        // feeOrder
        if ($day) {
            $feeOrderModel->endTime = $feeOrderModel->endTime + $day * 86400;
        }

        if ($date) {
            $feeOrderModel->endTime = strtotime($date) + 86399;

            if ($beforeEndTime >= $feeOrderModel->endTime) {
                throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "延期日期不能早于原日期");
            }
        }

        $feeOrderModel->save();

        // feeChanges
        (new FeeAnnualChangesModel())
            ->buildChanges('endTime', $beforeEndTime, $feeOrderModel->endTime)
            ->batchAdd($feeOrderNo, $userId, $userName, $feeOrderModel->shopId, $remark, $image);

        DB::commit();

        return ['endTime' => $feeOrderModel->endTime];
    }

    /**
     * 减免
     * @param string $feeOrderNo
     * @param int $price
     * @param int $userId
     * @param string $userName
     * @param string $remark
     * @param string $image
     * @return array
     */
    public static function reduce(
        string $feeOrderNo,
        int $price,
        int $userId,
        string $userName,
        string $remark,
        string $image = ""
    ): array {
        $feeOrderModel = self::checkFeeOrder($feeOrderNo);

        if ($feeOrderModel->shouldPayPrice - $feeOrderModel->payPrice < $price) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "减免费用不得低于剩余待支付金额");
        }

        DB::beginTransaction();

        // feeOrder
        $feeOrderModel->shouldPayPrice -= $price;
        if ($feeOrderModel->payPrice == $feeOrderModel->shouldPayPrice) {
            // $feeOrderModel->payStatus = FeeAnnualOrderModel::PAY_STATUS_OK;
        }
        $beforeManageFee = $feeOrderModel->manageFee;
        $beforeSystemFee = $feeOrderModel->systemFee;

        // 对应的减少明细费用
        if ($feeOrderModel->systemFee == $price) {

            // 优先考虑减数字费的情况
            $feeOrderModel->systemFee = 0;

        } else {

            // 从大到小减
            if ($feeOrderModel->manageFee >= $price) {
                $feeOrderModel->manageFee -= $price;
            } else {
                $feeOrderModel->manageFee = 0;
                $feeOrderModel->systemFee -= ($price - $beforeManageFee);
            }
        }

        $feeOrderModel->save();

        // feeChanges
        $changesModel = (new FeeAnnualChangesModel());

        if ($beforeManageFee != $feeOrderModel->manageFee) {
            $changesModel->buildChanges('manageFee', $beforeManageFee, $feeOrderModel->manageFee);
        }

        if ($beforeSystemFee != $feeOrderModel->systemFee) {
            $changesModel->buildChanges('systemFee', $beforeSystemFee, $feeOrderModel->systemFee);
        }

        $changesModel->batchAdd($feeOrderNo, $userId, $userName, $feeOrderModel->shopId, $remark, $image);

        DB::commit();

        return [
            'manageFee' => $feeOrderModel->manageFee,
            'systemFee' => $feeOrderModel->systemFee,
        ];
    }

    public static function getFeeTime(array $shopIds): array
    {
        return OpenShopMainProcessModel::query()
                                       ->join('open_shop_sign_order as sign', 'sign.mainProcessId', '=',
                                           'open_shop_main_process.id')
                                       ->whereIn('open_shop_main_process.shopId', $shopIds)
                                       ->where('sign.status', SignOrderEnum::ORDER_STATUS_COMPLETE)
                                       ->select(['shopId', 'startFeeTime'])
                                       ->get()
                                       ->map(function ($item) {
                                           $item['startFeeTime'] = $item['startFeeTime'] ? date('Y-m-d',
                                               strtotime($item['startFeeTime'])) : '-';

                                           return $item;
                                       })
                                       ->toArray();
    }

    /**
     * 编辑年管理费收取日期
     * @param int $shopId
     * @param int $date
     * @param int $userId
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public static function editFeeTime(int $shopId, int $date, int $userId, string $userName): void
    {
        $main = OpenShopMainProcessModel::query()
                                        ->join('open_shop_sign_order as sign', 'sign.mainProcessId', '=',
                                            'open_shop_main_process.id')
                                        ->where('sign.status', SignOrderEnum::ORDER_STATUS_COMPLETE)
                                        ->where('shopId', $shopId)->select('open_shop_main_process.*')
                                        ->first();
        if (!$main) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "不存在开店订单，不允许编辑");
        }

        $beforeStartFeeTime = $main->startFeeTime;

        DB::beginTransaction();

        $main->startFeeTime = $date;
        $main->save();

        // feeChanges
        (new FeeAnnualChangesModel())
            ->buildChanges('startFeeTime', $beforeStartFeeTime, $main->startFeeTime)
            ->batchAdd('', $userId, $userName, $shopId);

        DB::commit();
    }

    /**
     * 年费订单导出
     * @param $list
     * @return void
     */
    public static function exportFeeOrders($list)
    {
        ini_set('max_execution_time', 100000);
        header("Content-Disposition: attachment; filename=" . urlencode('年费订单导出') . date('Y-m-d') . '.csv');

        // UTF8的BOM头
        $fd = fopen('php://output', 'w+');
        fwrite($fd, "\xEF\xBB\xBF");

        // 表头
        fputcsv(
            $fd, [
                '门店编号',
                '门店名称',
                '应收金额',
                '商品明细',
                '实收金额',
                '支付状态',
                '年费开始计算日期',
                '到期时间',
            ]
        );
        $list->each(
            function ($item) use (&$fd) {
                fputcsv(
                    $fd, [
                        $item['shopCode'],
                        $item['shopName'],
                        $item['shouldPayPrice'] ? bcdiv($item['shouldPayPrice'], 100) : 0,
                        implode(',', $item['goodsDetail']),
                        $item['payPrice'] ? bcdiv($item['payPrice'], 100) : 0,
                        $item['payStatusText'],
                        $item['calculateTime'],
                        $item['endTime'],
                    ]
                );
                ob_flush();
                flush();
            }
        );

        fputcsv($fd, []);

        if (is_resource($fd)) {
            fclose($fd);
        }
        die;
    }

    /**
     * 年费订单0元支付
     * @param string $orderNo
     * @param string $bizId
     * @return void
     */
    public static function pay(string $orderNo, string $bizId)
    {
        // 新增一条支付流水
        $addPayLogId = OpenShopSignOrderPayHistoryModel::addHistory(
            $orderNo,
            0,
            0,
            CheckEnum::PAY_CHANNEL_BANK,
            OpenShopSignOrderPayHistoryModel::TYPE_FINAL,
            '年费订单支付',
            CheckEnum::SYS_TYPE_ANNUAL_FEE,
            $bizId
        );

        (new SignOrderService($orderNo, null, false, true))->paySuccess($addPayLogId, 0);
    }
}
